package org.zhaya.sdk.processors.condition;

import io.logz.sawmill.Condition;
import io.logz.sawmill.Doc;
import io.logz.sawmill.Template;
import io.logz.sawmill.TemplateService;
import io.logz.sawmill.annotations.ConditionProvider;
import io.logz.sawmill.parser.ConditionParser;
import io.logz.sawmill.utilities.JsonUtils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.inject.Inject;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

import static java.util.Objects.requireNonNull;

@ConditionProvider(type = "exclude", factory = ExcludeCondition.Factory.class)
public class ExcludeCondition implements Condition {

    private final String field;
    private final Function<Doc, Object> getValueFunction;

    public ExcludeCondition(String field, Function<Doc, Object> getValueFunction) {
        this.field = field;
        this.getValueFunction = getValueFunction;
    }

    @Override
    public boolean evaluate(Doc doc) {
        if (!doc.hasField(field)) {
            return true;
        }

        Object fieldValue = doc.getField(field);
        if (fieldValue instanceof String) {
            return !String.valueOf(fieldValue).contains(String.valueOf(getValueFunction.apply(doc)));
        } else if (fieldValue instanceof List) {
            return !((List) fieldValue).contains(getValueFunction.apply(doc));
        } else {
            return false;
        }
    }

    public static class Factory implements Condition.Factory {
        private final TemplateService templateService;

        @Inject
        public Factory(TemplateService templateService) {
            this.templateService = requireNonNull(templateService);
        }

        @Override
        public Condition create(Map<String, Object> config, ConditionParser conditionParser) {
            Configuration excludeConfig = JsonUtils.fromJsonMap(Configuration.class, config);
            return new ExcludeCondition(excludeConfig.getField(), createGetValueFunction(excludeConfig.getValue()));
        }

        private Function<Doc, Object> createGetValueFunction(Object value) {
            if (value instanceof String) {
                Template valueTemplate = templateService.createTemplate((String) value);
                return valueTemplate::render;
            } else {
                return (ignoredDoc) -> value;
            }
        }
    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static class Configuration {
        private String field;
        private Object value;

    }
}